package com.budwk.app.jim;

import cn.hutool.core.text.StrFormatter;
import com.alibaba.fastjson.JSONObject;
import com.budwk.app.jim.server.JimJwtTokenUtils;
import com.budwk.app.jim.server.JimJwtUserInfoBO;
import com.budwk.app.sqfw.constants.SqfwWebSocketMsgConstants;
import com.google.common.base.Joiner;
import org.apache.commons.lang3.StringUtils;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.plugins.mvc.websocket.AbstractWsEndpoint;
import org.nutz.plugins.mvc.websocket.NutWsConfigurator;
import org.nutz.plugins.mvc.websocket.WsHandler;

import javax.servlet.http.HttpSession;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ZY.Wang
 * @since 2023/6/15
 */
@IocBean
@ServerEndpoint(value = "/platform/sqfw/sqfwWebSocket", configurator = NutWsConfigurator.class)
public class SqfwWebSocket extends AbstractWsEndpoint {

    private static final ConcurrentHashMap<String, String> userIdSessionIdMap = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, Session> sessionIdSessionMap = new ConcurrentHashMap<>();

    @Override
    public void onOpen(Session session, EndpointConfig config) {
        String userId = getParam("userId", session);
        String token = getParam("webSocketToken", session);
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(token)) throw new RuntimeException("");

        JimJwtUserInfoBO infoByToken = JimJwtTokenUtils.getInfoByToken(token);
        if (infoByToken == null) throw new RuntimeException("");
        String tokenUserId = infoByToken.getUserId();
        if (!userId.equals(tokenUserId)) throw new RuntimeException("");

        if (userIdSessionIdMap.containsKey(userId)) {
            String sessionId = userIdSessionIdMap.get(userId);
            handlers.remove(sessionId);
            sessions.remove(sessionId);
            userIdSessionIdMap.remove(userId);
            sessionIdSessionMap.remove(sessionId);
        }

        changeSessionId(session);
        String sessionId = session.getId();
        userIdSessionIdMap.put(userId, sessionId);
        System.out.println(StrFormatter.format("" +
                "当前登录用户id:{},sessionId:{},当前在线用户数量:{}", userId, sessionId, userIdSessionIdMap.size()));
        WsHandler handler = createHandler(session, config);
        handler.setRoomProvider(roomProvider);
        handler.setSession(session);
        handler.setHttpSession((HttpSession) config.getUserProperties().get("HttpSession"));
        handler.setEndpoint(this);
        handler.init();
        if (!isUndertowSession(session))
            try {
                session.addMessageHandler(handler);
            } catch (Exception e) {
                System.out.println("skip addMessageHandler");
            }
        sessions.put(sessionId, session);
        handlers.put(sessionId, handler);

        sessionIdSessionMap.put(sessionId, session);
    }

    /**
     * 客户端放消息过来
     *
     * @param session 参数
     * @param msg     消息内容
     */
    @Override
    public void onMesssageString(Session session, String msg) {
        try {
            String sessionId = session.getId();
            WebSocketMsgDTO webSocketMsgDTO = JSONObject.parseObject(msg, WebSocketMsgDTO.class);
            String type = webSocketMsgDTO.getType();
            if (StringUtils.isBlank(type)) return;
            if (type.equals(SqfwWebSocketMsgConstants.client_heart)) {
                WebSocketMsgDTO heartMsg = new WebSocketMsgDTO(SqfwWebSocketMsgConstants.client_heart, SqfwWebSocketMsgConstants.server_response_heart);
                sendTextSync(sessionId, JSONObject.toJSONString(heartMsg));
            }
            super.onMesssageString(session, msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onClose(Session session, CloseReason closeReason) {
        sessionIdSessionMap.remove(session.getId());
        super.onClose(session, closeReason);
    }

    //--------------------------------------------------------------------------------
    // 下面是一些其他的方法
    //--------------------------------------------------------------------------------
    public boolean sendMessage(String toUserId, WebSocketMsgDTO msgDTO) {
        // 根据用户id查找到对应的sessionId
        String sessionId = userIdSessionIdMap.get(toUserId);
        System.out.println(StrFormatter.format("用户:{}的sessionId:{}", toUserId, sessionId));
        if (StringUtils.isNotBlank(sessionId)) {
            boolean sendFlag = sendTextSync(sessionId, JSONObject.toJSONString(msgDTO));
            System.out.println(StrFormatter.format("向用户{}，sessionId:{}发送消息:{},{}", toUserId, sessionId, msgDTO, sendFlag));
        }
        return false;
    }

    @Override
    public Session getSession(String sessionId, boolean opened) {
        Session session = sessionIdSessionMap.get(sessionId);
        if (session == null)
            return null;
        if (opened && !session.isOpen())
            return null;
        return session;
    }

    private String getParam(String key, Session session) {
        Map<String, List<String>> requestParameterMap = session.getRequestParameterMap();
        List<String> list = requestParameterMap.get(key);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return "";
    }
}
